package org.stone.project.common.utils;

import cn.hutool.extra.spring.SpringUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.stone.project.common.pojo.constant.SpringConstant;
import org.stone.project.common.pojo.constant.SysConstant;

import java.text.SimpleDateFormat;

/**
 * 序列化工具
 */
@Slf4j
public class JsonUtil {
    {
        defaultObjectMapper = new ObjectMapper();
        defaultObjectMapper.setDateFormat(new SimpleDateFormat(SysConstant.DATE_TIME_FORMATE));
        defaultObjectMapper.setTimeZone(SysConstant.gmt);
        defaultObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    /**
     * 默认的objectMapper，当spring环境不存在时的替代品
     */
    private static ObjectMapper defaultObjectMapper = null;

    /**
     * 获取通用jackson的ObjectMapper
     * @return
     */
    public static ObjectMapper getObjectMapper(){
        try {
            return SpringUtil.getBean(ObjectMapper.class);
        } catch (Exception e) {
            log.warn("使用默认序列化器");
            return defaultObjectMapper;
        }
    }

    /**
     * 获取添加class的ObjectMapper
     * @return
     */
    public static ObjectMapper getAddClassObjectMapper(){
        return SpringUtil.getBean(SpringConstant.ADD_CLASS_OBJECT_MAPPER,ObjectMapper.class);
    }

    /**
     * 对象json序列化
     * @param data
     * @return
     */
    @SneakyThrows
    public static String toJson(Object data){
        return getObjectMapper().writeValueAsString(data);
    }

    /**
     * 对象json序列化
     * @param data
     * @return
     */
    @SneakyThrows
    public static String toJson(ObjectMapper objectMapper,Object data){
        return objectMapper.writeValueAsString(data);
    }

    /**
     * 简单类型转换
     * @param json
     * @param clazz
     * @return
     * @param <T>
     */
    @SneakyThrows
    public static <T> T toObject(String json, Class <T> clazz){
        return getObjectMapper().readValue(json, clazz);
    }

    /**
     * 简单类型转换
     * @param json
     * @param clazz
     * @return
     * @param <T>
     */
    @SneakyThrows
    public static <T> T toObject(ObjectMapper objectMapper,String json, Class <T> clazz){
        return objectMapper.readValue(json, clazz);
    }

    /**
     * 复杂类型转换
     * @param json
     * @return
     * @param <T>
     */
    @SneakyThrows
    public static <T> T toObject(String json){
        CusTypeReference<T> typeReference = new CusTypeReference<>();
        return (T)getObjectMapper().readValue(json, typeReference);
    }

    public static class CusTypeReference<T> extends TypeReference{

    }
}
